<?php
class ProductController extends HomeController
{
    /** actionIndex =========================
     * @author   TuanNguyen
     * @desc     Show index page of product
     *
     * @param
     * @return
     * ============================================== */
    public function actionIndex()
    {
        //Init
        $arr_errorEnt           = array();
        $s_errorMsg             = null;
        $arr_category           = null;
        $arr_productsByCategory = null;

        #Region Set Category Entity to array
        $arr_category = self::getCategoryProduct();
        if( ErrorEntity::isErrorEntity($arr_category) )
        {
            array_push($arr_errorEnt, $arr_category);
            $arr_category = null;
        }
        #EndRegion

        //Set 12 new products for each category
        $arr_productsByCategory = self::GetNewProductByCategory($arr_category, $arr_errorEnt);
        
        //Set error Message if exist
        if ( count($arr_errorEnt) > 0 )
        {
            $s_errorMsg = self::getErrorMessage($arr_errorEnt);
        }

        $this->render(
            "index",
            array(
                "arr_category"           => $arr_category,
                "arr_productsByCategory" => $arr_productsByCategory,
                "s_errorMsg"             => $s_errorMsg
            )
        );//End render
    }//End actionIndex


    /** actionDetail =========================
     * @author   TuanNguyen
     * @desc     Show detail product page
     *
     * @param
     * @return
     * ============================================== */
    public function actionDetail()
    {
        #Region Init Param
        $arr_errorEnt    = array();
        $s_errorMsg      = null;
        $o_product       = null;
        $arr_category    = null;
        $s_urlCategory   = null;
        $s_urlCateParent = null;
        #EndRegion Init Param

        #Region Check Request Param
        $b_result = self::checkDetailParam();
        if( ErrorEntity::isErrorEntity($b_result) )
        {
            array_push($arr_errorEnt, $b_result);
            $o_product = null;
        }
        #EndRegion Check Request Param

        #Region Set Category Entity to array
        $arr_category = self::getCategoryProduct();
        if( ErrorEntity::isErrorEntity($arr_category) )
        {
            array_push($arr_errorEnt, $arr_category);
            $arr_category = null;
        }
        #EndRegion

        #Region Set detail of product
        if ( count($arr_errorEnt) == 0 )
        {
            $i_key     = $_REQUEST["key"];
            $o_product = Product::model()->findByPk($i_key);
        }

        if ( is_null($o_product) )
        {
            $o_product        = null;
            $o_error          = new ErrorEntity();
            $o_error->errCode = "ERR_5";
            $o_error->param   = null;
            array_push($arr_errorEnt, $o_error);
        }
        else 
        {
            $s_urlCategory = Yii::app()->createAbsoluteUrl( "product/search",
                    array ( "urlMapping" => $o_product->category0->url_mapping,
                            "category"   => $o_product->category0->identification,
                            "page"       => 1
                    )
            );

            if ($o_product->category0->parent > 0) 
            {
                $o_categoryParent = Category::model()->findByPk($o_product->category0->parent);

                if ( $o_categoryParent instanceof Category )
                {
                    $o_product->category0->parent_name =  $o_categoryParent->name;
                    $s_urlCateParent = Yii::app()->createAbsoluteUrl( "product/search",
                            array ( "urlMapping" => $o_categoryParent->url_mapping,
                                    "category"   => $o_categoryParent->identification,
                                    "page"       => 1
                            )
                    );
                }
            }//End if
        }//End else
        #EndRegion

        //Set error Message if exist
        if ( count($arr_errorEnt) > 0 )
        {
            $s_errorMsg = self::getErrorMessage($arr_errorEnt);
        }

        //Set render to template
        $this->render(
                "detail",
                array(
                    "s_urlCategory"   => $s_urlCategory,
                    "s_urlCateParent" => $s_urlCateParent,
                    "arr_category"    => $arr_category,
                    "o_product"       => $o_product,
                    "s_errorMsg"      => $s_errorMsg
                )
        );//End render
    }//End actionDetail


    /** actionSearch =========================
     * @author   TuanNguyen
     * @desc     Show product which is searched
     *
     * @param
     * @return
     * ============================================== */
    public function actionSearch()
    {
        if ( isset($_REQUEST["txt_tim"]) )
        {
            $_REQUEST["txt_tim"] = str_replace(" ", "-", $_REQUEST["txt_tim"]);
            $s_url = Yii::app()->createUrl( "product/search",
                                            array( "sSearch" => $_REQUEST["txt_tim"],
                                                   "page"    => 1
                                                 )
                                          );
            $this->redirect($s_url);
        }

        //Init param
        $arr_errorEnt    = array();
        $arr_category    = null;
        $arr_product     = null;
        $s_errorMsg      = null;
        $s_pageTitle     = null;
        $i_currentPage   = 1;
        $i_amountPerPage = 20;
        $i_totalItem     = 0;

        #Region Set Category Entity to array
        $arr_category = self::getCategoryProduct();
        if( ErrorEntity::isErrorEntity($arr_category) )
        {
            $s_errorMsg = self::getErrorMessage($arr_category);
            throw new CHttpException(500, $s_errorMsg);
        }
        #EndRegion

        #Region Check param search
        $b_result = self::checkSearchParam();
        if( ErrorEntity::isErrorEntity($b_result) )
        {
            array_push($arr_errorEnt, $b_result);
            $o_product = null;
        }
        #EndRegion

        #Region Set array of product
        if ( count($arr_errorEnt) == 0 )
        {
            $i_currentPage = $_REQUEST["page"];
            $s_order       = "`insert` DESC";
            $s_where       = null;

            if (isset($_REQUEST["category"]))
            {
                //$s_where = "category = ".$_REQUEST["category"];
                $s_where = "
                    (`category` IN ( SELECT sub_cate.`identification`
                                     FROM `category` sub_cate
                                     WHERE sub_cate.`parent` = ".$_REQUEST["category"].") OR
                    `category` = ".$_REQUEST["category"].") AND
                    `delete` IS NULL
                ";
            }
            elseif (isset($_REQUEST["sSearch"]))
            {
                $_REQUEST["sSearch"] = trim(str_replace("-", " ", $_REQUEST["sSearch"]));
                $arr_search          = explode(" ", $_REQUEST["sSearch"]);

                if (count($arr_search) > 0 && !empty($_REQUEST["sSearch"]) )
                {
                    $s_where   .= "`subject` LIKE '%".$_REQUEST["sSearch"]."%' OR ";

                    foreach ( $arr_search as $value )
                    {
                        $s_where  .= "`subject` LIKE '%".$value."%' OR ";
                    }

                    $s_where = substr($s_where, 0, -3);
                    $s_order = null;
                }//End if
            }//End elseif

            if ( !is_null($s_where) || $s_where != "" )
            {
                self::getProductsBySearch(1,10000,$s_order,$s_where, $i_totalItem);
                $arr_product = self::getProductsBySearch($i_currentPage,$i_amountPerPage,$s_order,$s_where, $i_totalItemPage);
                if( ErrorEntity::isErrorEntity($arr_product) )
                {
                    array_push($arr_errorEnt, $arr_product);
                    $arr_product = null;
                }
            }
            else 
            {
                $o_error          = new ErrorEntity();
                $o_error->errCode = "ERR_6";
                $o_error->param   = null;
                array_push($arr_errorEnt, $o_error);
            }
        }//End if
        #End Region

        //Set error Message if exist
        if ( count($arr_errorEnt) > 0 )
        {
            $s_errorMsg = self::getErrorMessage($arr_errorEnt);
        }

        //Set render to template
        $this->render(
            "search",
            array(
                "arr_category"    => $arr_category,
                "arr_product"     => $arr_product,
                "s_pageTitle"     => $s_pageTitle,
                "i_totalItem"     => $i_totalItem,
                "i_amountPerPage" => $i_amountPerPage,
                "i_currentPage"   => $i_currentPage,
                "s_errorMsg"      => $s_errorMsg
            )
        );//End render
    }//End actionSearch


    /** getCategoryProduct =========================
     * @author   TuanNguyen
     * @desc     Get all category of product
     *           Show to webpage
     * @param
     * @return   array Category or ErrorEntity
     * ============================================== */
    private function getCategoryProduct()
    {
        //Init
        $arr_category = null;
        $dataProvider = new CActiveDataProvider(
            "Category",
            array(
                "criteria"=>array(
                    "select" => " t.*,
                                  ( select count(cate.`identification`)
                                    from category cate 
                                    WHERE cate.`parent` = t.`identification`
                                   ) as `child_count`
                                "
                ),//End array criticle
            )//End array
        );

        //Get array of category models
        $arr_category = $dataProvider->data;
        if ( count($arr_category) == 0 )
        {
            $o_error          = new ErrorEntity();
            $o_error->errCode = "ERR_5";
            $o_error->param   = null;
            $arr_category     = $o_error;
        }

        return $arr_category;
    }//End getCategoryProduct


    /** getProductsBySearch =========================
     * @author   TuanNguyen
     * @desc     Get all product of key search
     *           Show to webpage
     * @param
     * @return   array Product or ErrorEntity
     * ============================================== */
    private function getProductsBySearch($i_page, $i_amountPerPage, $s_order, $s_where, &$i_totalItem)
    {
        //Init
        $arr_product =  null;
        $i_offset    = ($i_page - 1) * $i_amountPerPage;

        $dataProvider = new CActiveDataProvider(
                "product",
                array(
                        "criteria"=>array(
                                "condition" => $s_where,
                                "order"     => $s_order,
                                "offset"    => $i_offset,
                                "limit"     => $i_amountPerPage
                        ),//End array criticle
                        'pagination' => false
                )//End array
        );
        $i_totalItem = $dataProvider->itemCount;
        $arr_product = $dataProvider->data;
        if ( count($arr_product) == 0 )
        {
            $o_error          = new ErrorEntity();
            $o_error->errCode = "ERR_6";
            $o_error->param   = null;
            $arr_product     = $o_error;
        }

        return $arr_product;
    }//End getProductsBySearch


    /** GetNewProductByCategory =============================
     * @author   TuanNguyen
     * @desc     set 12 new product of each root category
     *           to show in index page of product
     * @param    $arr_rootCategory: array of categdory entity
     *            
     * @return   null: there are errors
     * ============================================== */
    private function GetNewProductByCategory($arr_category, &$arr_errorEnt)
    {
        //Init param
        $arr_rootCate = null;

        foreach ($arr_category as $index => $o_category)
        {
            if ( ($o_category instanceof Category) == true &&
                 $o_category->parent == 0 )
            {
                $s_condition = "
                    (`category` IN ( SELECT sub_cate.`identification` 
                                     FROM `category` sub_cate
                                     WHERE sub_cate.`parent` = ".$o_category->identification.") OR 
                    `category` = ".$o_category->identification.") AND 
                    `delete` IS NULL
                ";
                
                //Get product by root category
                $dataProvider = new CActiveDataProvider(
                        "Product",
                        array(
                                "criteria"=>array(
                                        "condition"=> $s_condition,
                                        "order"=>"`insert` DESC"
                                ),//End array criticle
                                "pagination"=>array(
                                        "pageSize"=>12
                                )//End array pagination
                        )//End array
                );
                
                $arr_rootCate[$o_category->identification] = array(
                    "categoryName" => $o_category->name,
                    "arrProduct"   => $dataProvider->data
                );
            }//End if
            else
            {
                $o_error          = new ErrorEntity();
                $o_error->errCode = "ERR_1";
                $o_error->param   = null;
                array_push($arr_errorEnt, $o_error);
                continue;
            }
        }//End foreach

        return $arr_rootCate;
    }//End GetNewProductByCategory


    /** checkDetailParam =========================
     * @author   TuanNguyen
     * @desc     Check request param when user call deatail product page
     *           set reference parameter if there are an error
     * @param
     * @return   null or ErrorEntity
     * ============================================== */
    private function checkDetailParam()
    {
        $o_error = new ErrorEntity();

        if( isset($_REQUEST["urlMapping"]) == false ||
            isset($_REQUEST["key"])        == false )
        {
            $o_error->errCode   = "ERR_3";
            $o_error->param     = null;
            return $o_error;
        }

        if ( is_numeric($_REQUEST["key"]) == false)
        {
            $o_error->errCode   = "ERR_4";
            $o_error->param     = array("fieldName"=>"item key", "formatName"=>"interger");
            return $o_error;
        }
    }//End checkDetailParam


    /** checkSearchParam =========================
     * @author   TuanNguyen
     * @desc     Check request param when user call deatail product page
     *           set reference parameter if there are an error
     * @param
     * @return   null or ErrorEntity
     * ============================================== */
    private function checkSearchParam()
    {
        $o_error = new ErrorEntity();
    
        if( isset($_REQUEST["sSearch"]) == false &&
            ( isset($_REQUEST["urlMapping"]) == false ||
              isset($_REQUEST["category"])   == false ) )
        {
            $o_error->errCode   = "ERR_3";
            $o_error->param     = null;
            return $o_error;
        }
    
        if ( isset($_REQUEST["sSearch"]) == false &&
             is_numeric($_REQUEST["category"]) == false )
        {
            $o_error->errCode   = "ERR_4";
            $o_error->param     = array("fieldName"=>"item category", "formatName"=>"interger");
            return $o_error;
        }

        return null;
    }//End checkSearchParam


    /** getErrorMessage =============================
     * @author   TuanNguyen
     * @desc     get error message from array of error entity
     *           set reference parameter if there are an error
     * @param    $errorEnts: array of error entity or error entity
     * @return   string: error message
     * ============================================== */
    private function getErrorMessage($errorEnts)
    {
        $arr_errorMessage    = array(
                "ERR_1" => "There are an error with parameters in SQL statement. ",
                "ERR_2" => "SQLException",
                "ERR_3" => "Recieved Parameter is wrong or missing. ",
                "ERR_4" => "format of fieldName is formatName, please type value as formatName format . ",
                "ERR_5" => "Data is updating...",
                "ERR_6" => "Không tìm thấy kết quả phù hợp.",
        );
    
        //Return error message
        if ( is_array($errorEnts) )
        {
            return ErrorEntity::setErrorMessageByArray($errorEnts, $arr_errorMessage);
        }
        elseif ( $errorEnts instanceof ErrorEntity )
        {
            return ErrorEntity::setErrorMessageByEntity($errorEnts, $arr_errorMessage);
        }
    }
}